#pragma once
#include <vector>
#include <functional>
#include <mutex> 
#include <condition_variable>

template <class T> 
class SyncEventQueue
{ 
public:
    typedef  std::function<void(T )> Processor; 
    void push(T item)
    {
	{
	    std::lock_guard<std::mutex> guard(m_mutex);
	    m_data.push_back(item); 
	}
	m_cond.notify_one();
    }

    
    // single thread 
    void process(Processor processor)
    {
	if (m_data.empty())
	{
	    std::unique_lock<std::mutex> lock(m_mutex);
	    m_cond.wait(lock);
	}
	{
	    std::unique_lock<std::mutex> lock(m_mutex);
	    m_data.swap(m_cache);

	}


	for(auto item : m_cache)
	{
		processor(item); 
	} 
	m_cache.clear(); 
    }

    int notify() {
	m_cond.notify_one();
    }
  
private: 
    std::mutex  m_mutex; 
    std::condition_variable m_cond;
    std::vector<T> m_data;  
    std::vector<T> m_cache;  
}; 


